﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.Drawing;
using popLib;
using System.Windows.Forms.VisualStyles;
using System.ComponentModel;
using popLib.ModelSystem;

namespace popLib.CustomeControl
{
    public class ExDateTimePicker : DateTimePicker
    {
        Panel panel;
        TextBox textbox;

        private Color _ForeColor = SystemColors.WindowText;
        [Browsable(true)]
        public override Color ForeColor
        {
            get { return _ForeColor; }
            set { 
                _ForeColor = value;

                if (_ForeColor != SystemColors.WindowText)
                    this.SetStyle(ControlStyles.UserPaint, true); 
                else
                    this.SetStyle(ControlStyles.UserPaint, false);                
            }
        }

        [Browsable(true)]
        public bool HideInputTextBox
        {
            get { return !textbox.Visible; }
            set { textbox.Visible = !value; }
        }

        public enum GetDateTimeMethodType { LocalDateTime, ModelSystemDateTime, CustomeDateTimeFunction }
        public GetDateTimeMethodType GetDateTimeMethod { get; set; }
        public delegate DateTime CustomeDateTimeFunctionDelegate();
        public CustomeDateTimeFunctionDelegate CustomeDateTimeFunction { get; set; }

        public DateTime CurrentDateTime
        {
            get
            {
                switch (GetDateTimeMethod)
                {
                    case GetDateTimeMethodType.LocalDateTime:
                        return DateTime.Now; 
                    case GetDateTimeMethodType.ModelSystemDateTime:
                        return MainFormModel.GetServerDateTime();
                    case GetDateTimeMethodType.CustomeDateTimeFunction:
                        if (CustomeDateTimeFunction != null)
                            return CustomeDateTimeFunction();
                        return DateTime.Now;
                    default:
                        return DateTime.Now;
                }
            }
        }

        public ExDateTimePicker()
        {
            panel = new Panel();            
            panel.Height = this.Height;
            panel.Width = this.Width - 22;
            this.Controls.Add(panel);

            textbox = new TextBox();
            textbox.Top = 2;
            textbox.Left = 2;
            textbox.Height = Height;
            textbox.ForeColor = ForeColor;
            textbox.BorderStyle = BorderStyle.None;
            textbox.Visible = true;
            panel.Controls.Add(textbox);

            textbox.BringToFront();
            textbox.LostFocus += new EventHandler(textbox_LostFocus);
            textbox.KeyDown += new KeyEventHandler(textbox_KeyDown);
            updatePanel();
        }

        

        void textbox_KeyDown(object sender, KeyEventArgs e)
        {

            if (e.KeyCode == Keys.Enter)
                textbox_LostFocus(e, new EventArgs());
            if (e.KeyCode == Keys.Escape)
            {
                textbox.Clear();
            }
        }

        void textbox_LostFocus(object sender, EventArgs e)
        {

            if (isReadOnly) return;
            if (!StringLib.isValid(textbox.Text)) return;
            string[] parts = StringLib.SplitByAny(textbox.Text, "/\\-.");

            try
            {
                if (CustomFormat.Contains("y") && CustomFormat.Contains("M") && CustomFormat.Contains("d"))
                {
                    if (parts.Length == 1)
                        this.Value = new DateTime(GetDatePart(parts.Length >= 1 ? parts[0] : "", DatePart.Year, true), 1, 1);
                    else if (CustomFormat.StartsWith("y"))
                        this.Value = new DateTime(
                            GetDatePart(parts.Length >= 1 ? parts[0] : "", DatePart.Year, true),
                            GetDatePart(parts.Length >= 2 ? parts[1] : "", DatePart.Month, true),
                            GetDatePart(parts.Length >= 3 ? parts[2] : "", DatePart.Day, true));
                    else if (CustomFormat.IndexOf("M") < CustomFormat.IndexOf("d"))
                        this.Value = new DateTime(
                            GetDatePart(parts.Length >= 3 ? parts[2] : "", DatePart.Year, true),
                            GetDatePart(parts.Length >= 1 ? parts[0] : "", DatePart.Month, true),
                            GetDatePart(parts.Length >= 2 ? parts[1] : "", DatePart.Day, true));
                    else
                        this.Value = new DateTime(
                            GetDatePart(parts.Length >= 3 ? parts[2] : "", DatePart.Year, true),
                            GetDatePart(parts.Length >= 2 ? parts[1] : "", DatePart.Month, true),
                            GetDatePart(parts.Length >= 1 ? parts[0] : "", DatePart.Day, true));

                }
                else if (CustomFormat.Contains("y") && CustomFormat.Contains("M"))
                {
                    if(CustomFormat.IndexOf("M") < CustomFormat.IndexOf("y"))
                        this.Value = new DateTime(GetDatePart(parts.Length >= 2 ? parts[1] : "", DatePart.Year, true), 
                            GetDatePart(parts.Length >= 1 ? parts[0] : "", DatePart.Month, true), 1);
                    else
                        this.Value = new DateTime(GetDatePart(parts.Length >= 1 ? parts[0] : "", DatePart.Year, true),
                            GetDatePart(parts.Length >= 2 ? parts[1] : "", DatePart.Month, true), 1);
                }
                else if(CustomFormat.Contains("y"))
                {
                    this.Value = new DateTime(GetDatePart(parts.Length >= 1 ? parts[0] : "", DatePart.Year, true), 1, 1);
                }

                panel.Hide();
            }
            catch
            {
                textbox.LostFocus -= new EventHandler(textbox_LostFocus);
                FormLib.alert("Ngày nhập không hợp lệ!!\r\nXin vui lòng nhập ngày theo định dạng sau: \r\n    ngày\\tháng\\năm\r\n    ngày-tháng-năm\r\n    ngày.tháng.năm", "Thông báo");
                textbox.LostFocus += new EventHandler(textbox_LostFocus);
                //textbox.Focus();
                textbox.Clear();
            }
        }

        private enum DatePart{ Day, Month, Year }
        private int GetDatePart(string value, DatePart part, bool defaultCurrentDate)
        {
            int number = NumberLib.getInt(value);
            switch (part)
            {
                case DatePart.Day:
                    number = number == 0 ? defaultCurrentDate ? CurrentDateTime.Day : 1 : number;
                    number = number > 31 ? 31 : number;
                    break;
                case DatePart.Month:
                    number = number == 0 ? defaultCurrentDate ? CurrentDateTime.Month : 1 : number;
                    number = number > 12 ? 12 : number;
                    break;
                case DatePart.Year:
                    number = number == 0 ? CurrentDateTime.Year : number;
                    number = number < 1000 ? number + 2000 : number;
                    break;
            }
            return number;
        }

        private bool isReadOnly;

        public bool ReadOnly
        {
            get { return isReadOnly; }
            set
            {
                isReadOnly = value;
                updatePanel();
            }
        }

        private bool isnull;
        public bool IsNull
        {
            get { return isnull; }
            set
            {
                isnull = value;
                updatePanel();
            }
        }

        public DateTime Values
        {
            get
            {
                if (IsNull)
                {
                    return DateTimeLib.NullDateTime;
                }
                else
                {
                    return Value;
                }
            }
            set
            {
                isResetValue = true;

                if (value.Date == DateTimeLib.NullDateTime)
                {                
                    IsNull = true;
                }
                else
                {                    
                    IsNull = false;
                }

                this.Value = value;

                isResetValue = false;

                
            }
        }


        private void updatePanel()
        {
            textbox.ReadOnly = isReadOnly;
            textbox.Text = isnull ? "" : this.Text;
            textbox.Visible = panel.Visible = isnull || isReadOnly;            

            panel.BackColor = textbox.BackColor = isReadOnly ? System.Drawing.SystemColors.Control : System.Drawing.SystemColors.Window;
            panel.Width = isReadOnly ? ClientRectangle.Width : ClientRectangle.Width - 22;
            textbox.Width = panel.Width;
        }

        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            updatePanel();
        }

        private bool isResetValue = false;
        protected override void OnValueChanged(EventArgs eventargs)
        {
            if (isResetValue == false)
            {
                IsNull = false;
            }
            else
            {
                updatePanel();
            }

            base.OnValueChanged(eventargs);

        }

        protected override void OnEnter(EventArgs e)
        {
            base.OnEnter(e);
            if (textbox.Visible)
            {
                textbox.Focus();
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            if (ForeColor != SystemColors.WindowText)
            {
                Graphics g = this.CreateGraphics();
                g.FillRectangle(new SolidBrush(this.BackColor), 0, 0, ClientRectangle.Width, ClientRectangle.Height);
                g.DrawString(this.Text, this.Font, new SolidBrush(ForeColor), 0, 2);

                Rectangle dropDownRectangle = new Rectangle(ClientRectangle.Width - 17, 0, 17, ClientRectangle.Height);
                ComboBoxRenderer.DrawDropDownButton(g, dropDownRectangle, this.Enabled ? ComboBoxState.Normal : ComboBoxState.Disabled);
            }
            else
            {
                base.OnPaint(e);
            }
        }

    }
}
